home *** CD-ROM | disk | FTP | other *** search
/ Programmer Plus 2007 / Programmer-Plus-2007.iso / Programming / Report Writers / Crystal Repot 9.0 Full CD version / Setup.exe / SRC / HOARDDLL.ZIP / 3rdParty / hoard / libhoard-2.0.2 / heap.h < prev    next >
Encoding:
C/C++ Source or Header  |  2002-06-18  |  16.8 KB  |  616 lines

  1. ///-*-C++-*-//////////////////////////////////////////////////////////////////
  2. //
  3. // Hoard: A Fast, Scalable, and Memory-Efficient Allocator
  4. //        for Shared-Memory Multiprocessors
  5. // Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery
  6. //
  7. // Copyright (c) 1998-2000, The University of Texas at Austin.
  8. //
  9. // This library is free software; you can redistribute it and/or modify
  10. // it under the terms of the GNU Library General Public License as
  11. // published by the Free Software Foundation, http://www.fsf.org.
  12. //
  13. // This library is distributed in the hope that it will be useful, but
  14. // WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16. // Library General Public License for more details.
  17. //
  18. //////////////////////////////////////////////////////////////////////////////
  19.  
  20.  
  21. //////////////////////////////////////////////////////////////////////////////
  22. //
  23. // Note: This file was modified by Crystal Decisions in June 2002.
  24. //
  25. //////////////////////////////////////////////////////////////////////////////
  26.  
  27.  
  28. /*
  29.   heap.h
  30.   ------------------------------------------------------------------------
  31.   hoardHeap, the base class for threadHeap and processHeap.
  32.   ------------------------------------------------------------------------
  33.   @(#) $Id: heap.h,v 1.67 2000/03/27 21:55:27 emery Exp $
  34.   ------------------------------------------------------------------------
  35.   Emery Berger                    | <http://www.cs.utexas.edu/users/emery>
  36.   Department of Computer Sciences |             <http://www.cs.utexas.edu>
  37.   University of Texas at Austin   |                <http://www.utexas.edu>
  38.   ========================================================================
  39. */
  40.  
  41.  
  42. #ifndef _HEAP_H_
  43. #define _HEAP_H_
  44.  
  45. #include "config.h"
  46.  
  47. #include <assert.h>
  48. #include <math.h>
  49.  
  50. #include "arch-specific.h"
  51. #include "superblock.h"
  52. #include "heapstats.h"
  53.  
  54. class processHeap; // forward declaration
  55.  
  56.  
  57. class hoardHeap {
  58.  
  59. public:
  60.  
  61.   hoardHeap (void);
  62.  
  63. #if !defined(CRYSTAL_HOARD)
  64.   // A superblock that holds more than one object must hold at least
  65.   // this many bytes.
  66.   enum { SUPERBLOCK_SIZE = 8192 };
  67. #else
  68.   // Superblocks are grouped into different classes, rather than a
  69.   // single class of size SUPERBLOCK_SIZE.
  70.   #ifdef WIN32
  71.   enum { SUPERBLOCK_CLASSES = 1 };
  72.   #else
  73.   enum { SUPERBLOCK_CLASSES = 3 };
  74.   #endif
  75. #endif
  76.  
  77.   // A thread heap must be at least 1/EMPTY_FRACTION empty before we
  78.   // start returning superblocks to the process heap.
  79.   enum { EMPTY_FRACTION = SUPERBLOCK_FULLNESS_GROUP - 1 };
  80.  
  81.   // Reset value for the least-empty bin.  The last bin
  82.   // (SUPERBLOCK_FULLNESS_GROUP-1) is for completely full superblocks,
  83.   // so we use the next-to-last bin.
  84.   enum { RESET_LEAST_EMPTY_BIN = SUPERBLOCK_FULLNESS_GROUP - 2 };
  85.  
  86.   // The number of empty superblocks that we allow any thread heap to
  87.   // hold once the thread heap has fallen below 1/EMPTY_FRACTION
  88.   // empty.
  89.   enum { MAX_EMPTY_SUPERBLOCKS = EMPTY_FRACTION };
  90.  
  91.   // The maximum number of thread heaps we allow.  (NOT the maximum
  92.   // number of threads -- Hoard imposes no such limit.)  This must be
  93.   // a power of two! NB: This number is twice the maximum number of
  94.   // PROCESSORS supported by Hoard.
  95.   enum { MAX_HEAPS = 128 };
  96.  
  97.   // ANDing with this rounds to MAX_HEAPS.
  98.   enum { MAX_HEAPS_MASK = MAX_HEAPS - 1 };
  99.  
  100.   //
  101.   // The number of size classes.  This combined with the
  102.   // SIZE_CLASS_BASE determine the maximum size of an object.
  103.   //
  104.   // NB: Once this is changed, you must execute maketable.cpp and put
  105.   // the generated values into heap.cpp.
  106.   enum { SIZE_CLASSES = 115 };
  107.  
  108.   // Every object is aligned so that it can always hold a double.
  109.   enum { ALIGNMENT = sizeof(double) };
  110.  
  111.   // ANDing with this rounds to ALIGNMENT.
  112.   enum { ALIGNMENT_MASK = ALIGNMENT - 1};
  113.  
  114.   // Used for sanity checking.
  115.   enum { HEAP_MAGIC = 0x0badcafe };
  116.  
  117.   // Get the usage and allocated statistics.
  118.   inline void getStats (int sizeclass, int& U, int& A);
  119.  
  120.  
  121. #if HEAP_STATS
  122.   // How much is the maximum ever in use for this size class?
  123.   inline int maxInUse (int sizeclass);
  124.  
  125.   // How much is the maximum memory allocated for this size class?
  126.   inline int maxAllocated (int sizeclass);
  127. #endif
  128.  
  129.   // Insert a superblock into our list.
  130.   void  insertSuperblock (int sizeclass,
  131.              superblock * sb,
  132.              processHeap * pHeap);
  133.  
  134.   // Remove the superblock with the most free space.
  135.   superblock * removeMaxSuperblock (int sizeclass);
  136.  
  137.   // Find an available superblock (i.e., with some space in it).
  138.   inline superblock * findAvailableSuperblock (int sizeclass,
  139.                            block *& b,
  140.                            processHeap * pHeap);
  141.  
  142.   // Lock this heap.
  143.   inline void lock (void);
  144.  
  145.   // Unlock this heap.
  146.   inline void unlock (void);
  147.  
  148.   // Set our index number (which heap we are).
  149.   inline void setIndex (int i);
  150.  
  151.   // Get our index number (which heap we are).
  152.   inline int getIndex (void);
  153.  
  154.   // Free a block into a superblock.
  155.   // This is used by processHeap::free().
  156.   // Returns 1 iff the superblock was munmapped.
  157.   int freeBlock (block *& b,
  158.          superblock *& sb,
  159.          int sizeclass,
  160.          processHeap * pHeap);
  161.  
  162.   //// Utility functions ////
  163.  
  164.   // Return the size class for a given size.
  165.   inline static int sizeClass (const size_t sz);
  166.  
  167.   // Return the size corresponding to a given size class.
  168.   inline static size_t sizeFromClass (const int sizeclass);
  169.  
  170.   // Return the release threshold corresponding to a given size class.
  171.   inline static int getReleaseThreshold (const int sizeclass);
  172.  
  173.   // Return how many blocks of a given size class fit into a superblock.
  174.   inline static int numBlocks (const int sizeclass);
  175.  
  176.   // Align a value.
  177.   inline static size_t align (const size_t sz);
  178.  
  179. #ifdef CRYSTAL_HOARD
  180.   // Return the class of superblock which holds blocks of the given size class
  181.   inline static int superblockClass(const int sizeclass);
  182.  
  183.   inline static size_t superblockSizeFromClass(const int superblockClass);
  184.  
  185.   // release superblock if the reusableBlockLimit is reached
  186.   bool unsbrkIfLimit(processHeap * pHeap, superblock * sb);
  187.  
  188. #endif
  189.  
  190. private:
  191.  
  192.   // Disable copying and assignment.
  193.  
  194.   hoardHeap (const hoardHeap&);
  195.   const hoardHeap& operator= (const hoardHeap&);
  196.  
  197.   // Recycle a superblock.
  198.   inline void recycle (superblock *);
  199.  
  200.   // Reuse a superblock (if one is available).
  201.   inline superblock * reuse (int sizeclass);
  202.  
  203.   // Remove a particular superblock.
  204.   void removeSuperblock (superblock *, int sizeclass);
  205.  
  206.   // Move a particular superblock from one bin to another.
  207.   void moveSuperblock (superblock *,
  208.                int sizeclass,
  209.                int fromBin,
  210.                int toBin);
  211.  
  212.   // Update memory in-use and allocated statistics.
  213.   // (*UStats = just update U.)
  214.   inline void incStats (int sizeclass, int updateU, int updateA);
  215.   inline void incUStats (int sizeclass);
  216.  
  217.   inline void decStats (int sizeclass, int updateU, int updateA);
  218.   inline void decUStats (int sizeclass);
  219.  
  220.   //// Members ////
  221.  
  222. #if HEAP_DEBUG
  223.   // For sanity checking.
  224.   const unsigned long _magic;
  225. #else
  226.   #define _magic HEAP_MAGIC
  227. #endif
  228.  
  229.   // Heap statistics.
  230.   heapStats    _stats[SIZE_CLASSES];
  231.  
  232.   // The per-heap lock.
  233. #ifdef WIN32 
  234.   hoardLockTypeS _lock;
  235. #else
  236.   hoardLockType _lock;
  237. #endif
  238.  
  239.   // Which heap this is (0 = the process (global) heap).
  240.   int _index;
  241.  
  242.   // Reusable superblocks.
  243. #ifndef CRYSTAL_HOARD
  244.   superblock *    _reusableSuperblocks;
  245.   int           _reusableSuperblocksCount;
  246. #else
  247.   superblock *  _reusableSuperblocks[SUPERBLOCK_CLASSES];
  248.   int           _reusableSuperblocksCount[SUPERBLOCK_CLASSES];
  249.  
  250.   // The lookup table for superblock class size
  251.   static size_t _superblockSize[SUPERBLOCK_CLASSES];
  252.  
  253.   // The lookup table for the limit of empty superblocks on the reusable list
  254.   static int    _reusableSuperblockLimit[SUPERBLOCK_CLASSES];
  255. #endif
  256.  
  257.   // Lists of superblocks.
  258.   superblock *    _superblocks[SUPERBLOCK_FULLNESS_GROUP][SIZE_CLASSES];
  259.  
  260.   // The current least-empty superblock bin.
  261.   int    _leastEmptyBin[SIZE_CLASSES];
  262.  
  263.   // The lookup table for size classes.
  264.   static size_t    _sizeTable[SIZE_CLASSES];
  265.  
  266.   // The lookup table for release thresholds.
  267.   static size_t    _threshold[SIZE_CLASSES];
  268. };
  269.  
  270.  
  271.  
  272. void hoardHeap::incStats (int sizeclass, int updateU, int updateA) {
  273.   assert (_magic == HEAP_MAGIC);
  274.   assert (updateU >= 0);
  275.   assert (updateA >= 0);
  276.   assert (sizeclass >= 0);
  277.   assert (sizeclass < SIZE_CLASSES);
  278.   _stats[sizeclass].incStats (updateU, updateA);
  279. }
  280.  
  281.  
  282.  
  283. void hoardHeap::incUStats (int sizeclass) {
  284.   assert (_magic == HEAP_MAGIC);
  285.   assert (sizeclass >= 0);
  286.   assert (sizeclass < SIZE_CLASSES);
  287.   _stats[sizeclass].incUStats ();
  288. }
  289.  
  290.  
  291. void hoardHeap::decStats (int sizeclass, int updateU, int updateA) {
  292.   assert (_magic == HEAP_MAGIC);
  293.   assert (updateU >= 0);
  294.   assert (updateA >= 0);
  295.   assert (sizeclass >= 0);
  296.   assert (sizeclass < SIZE_CLASSES);
  297.   _stats[sizeclass].decStats (updateU, updateA);
  298. }
  299.  
  300.  
  301. void hoardHeap::decUStats (int sizeclass)
  302. {
  303.   assert (_magic == HEAP_MAGIC);
  304.   assert (sizeclass >= 0);
  305.   assert (sizeclass < SIZE_CLASSES);
  306.   _stats[sizeclass].decUStats();
  307. }
  308.  
  309.  
  310. void hoardHeap::getStats (int sizeclass, int& U, int& A) {
  311.   assert (_magic == HEAP_MAGIC);
  312.   assert (sizeclass >= 0);
  313.   assert (sizeclass < SIZE_CLASSES);
  314.   _stats[sizeclass].getStats (U, A);
  315. }
  316.  
  317.  
  318. #if HEAP_STATS
  319. int hoardHeap::maxInUse (int sizeclass) {
  320.   assert (_magic == HEAP_MAGIC);
  321.   return _stats[sizeclass].getUmax();
  322. }
  323.  
  324.  
  325. int hoardHeap::maxAllocated (int sizeclass) {
  326.   assert (_magic == HEAP_MAGIC);
  327.   return _stats[sizeclass].getAmax(); 
  328. }
  329. #endif
  330.  
  331.  
  332. superblock * hoardHeap::findAvailableSuperblock (int sizeclass,
  333.                          block *& b,
  334.                          processHeap * pHeap)
  335. {
  336.   assert (this);
  337.   assert (_magic == HEAP_MAGIC);
  338.   assert (sizeclass >= 0);
  339.   assert (sizeclass < SIZE_CLASSES);
  340.  
  341.   superblock * sb = NULL;
  342.   int reUsed = 0;
  343.  
  344.   // Look through the superblocks, starting with the almost-full ones
  345.   // and going to the emptiest ones.  The Least Empty Bin for a
  346.   // sizeclass is a conservative approximation (fixed after one
  347.   // iteration) of the first bin that has superblocks in it, starting
  348.   // with (surprise) the least-empty bin.
  349.  
  350.   for (int i = _leastEmptyBin[sizeclass]; i >= 0; i--) {
  351.     sb = _superblocks[i][sizeclass];
  352.     if (sb == NULL) {
  353.       if (i == _leastEmptyBin[sizeclass]) {
  354.     // There wasn't a superblock in this bin,
  355.     // so we adjust the least empty bin.
  356.     _leastEmptyBin[sizeclass]--;
  357.       }
  358.     } else {
  359.       assert (sb->getOwner() == this);
  360.       break;
  361.     }
  362.   } 
  363.  
  364. #if 1
  365.   if (sb == NULL) {
  366.     // Try to reuse a superblock.
  367.     sb = reuse (sizeclass);
  368.     if (sb) {
  369.       assert (sb->getOwner() == this);
  370.       reUsed = 1;
  371.     }
  372.   }
  373. #endif
  374.  
  375.   if (sb != NULL) {
  376.     // Sanity checks:
  377.     //   This superblock is 'valid'.
  378.     assert (sb->isValid());
  379.     //   This superblock has the right ownership.
  380.     assert (sb->getOwner() == this);
  381.     
  382.     int oldFullness = sb->getFullness();
  383.  
  384.     // Now get a block from the superblock.
  385.     // This superblock must have space available.
  386.     b = sb->getBlock();
  387.     assert (b != NULL);
  388.     
  389.     // Update the stats.
  390.     incUStats (sizeclass);
  391.     
  392.     if (reUsed) {
  393.       insertSuperblock (sizeclass, sb, pHeap);
  394.       // Fix the stats (since insert will just have incremented them
  395.       // by this amount).
  396.       decStats (sizeclass,
  397.         sb->getNumBlocks() - sb->getNumAvailable(),
  398.         sb->getNumBlocks());
  399.     } else {
  400.       // If we've crossed a fullness group,
  401.       // move the superblock.
  402.       int fullness = sb->getFullness();
  403.       
  404.       if (fullness != oldFullness) {
  405.     // Move the superblock.
  406.     moveSuperblock (sb, sizeclass, oldFullness, fullness);
  407.       }
  408.     }
  409.   }
  410.  
  411.   // Either we didn't find a superblock or we did and got a block.
  412.   assert ((sb == NULL) || (b != NULL));
  413.   // Either we didn't get a block or we did and we also got a superblock.
  414.   assert ((b == NULL) || (sb != NULL));
  415.  
  416.   return sb;
  417. }
  418.  
  419.  
  420. int hoardHeap::sizeClass (const size_t sz) {
  421.   // Find the size class for a given object size
  422.   // (the smallest i such that _sizeTable[i] >= sz).
  423.   int sizeclass = 0;
  424.   while (_sizeTable[sizeclass] < sz) 
  425.     {
  426.       sizeclass++;
  427.       assert (sizeclass < SIZE_CLASSES);
  428.     }
  429.   return sizeclass;
  430. }
  431.  
  432.  
  433. size_t hoardHeap::sizeFromClass (const int sizeclass) {
  434.   assert (sizeclass >= 0);
  435.   assert (sizeclass < SIZE_CLASSES);
  436.   return _sizeTable[sizeclass];
  437. }
  438.  
  439.  
  440. int hoardHeap::getReleaseThreshold (const int sizeclass) {
  441.   assert (sizeclass >= 0);
  442.   assert (sizeclass < SIZE_CLASSES);
  443.   return _threshold[sizeclass];
  444. }
  445.  
  446.  
  447. int hoardHeap::numBlocks (const int sizeclass) {
  448.   assert (sizeclass >= 0);
  449.   assert (sizeclass < SIZE_CLASSES);
  450.   const size_t s = sizeFromClass (sizeclass);
  451.   assert (s > 0);
  452.   const int blksize = align (sizeof(block) + s);
  453.   // Compute the number of blocks that will go into this superblock.
  454. #ifndef CRYSTAL_HOARD
  455.   int nb = MAX (1, ((SUPERBLOCK_SIZE - sizeof(superblock)) / blksize));
  456. #else
  457.   int nb = 1;
  458.   int sbClass = 0;
  459.   while ( (sbClass < SUPERBLOCK_CLASSES) && nb == 1 )
  460.   {
  461.     nb = MAX(1, ((_superblockSize[sbClass] - sizeof(superblock)) / blksize));
  462.     sbClass++;
  463.   }
  464. #endif
  465.   return nb;
  466. }
  467.  
  468.  
  469. #ifdef CRYSTAL_HOARD
  470. int hoardHeap::superblockClass(const int sizeclass)
  471. {
  472.   assert (sizeclass >= 0);
  473.   assert (sizeclass < SIZE_CLASSES);
  474.   const size_t s = sizeFromClass (sizeclass);
  475.   assert (s > 0);
  476.   const int blksize = align (sizeof(block) + s);
  477.  
  478.   int nb = 1;
  479.   int sbClass = 0;
  480.   do
  481.   {
  482.     nb = MAX(1, ((_superblockSize[sbClass] - sizeof(superblock)) / blksize));
  483.   }
  484.   while ( (nb == 1) && (++sbClass < SUPERBLOCK_CLASSES) );
  485.  
  486.   return sbClass;
  487. }
  488.  
  489.  
  490. size_t hoardHeap::superblockSizeFromClass(const int superblockClass)
  491. {
  492.   assert (superblockClass >= 0);
  493.   assert (superblockClass < SUPERBLOCK_CLASSES);
  494.   return _superblockSize[superblockClass];
  495. }
  496. #endif  // CRYSTAL_HOARD
  497.  
  498.  
  499. void hoardHeap::lock (void) 
  500. {
  501.   assert (_magic == HEAP_MAGIC);
  502.   hoardLock (_lock);
  503. }
  504.  
  505.  
  506. void hoardHeap::unlock (void) {
  507.   assert (_magic == HEAP_MAGIC);
  508.   hoardUnlock (_lock);
  509. }
  510.  
  511.  
  512. size_t hoardHeap::align (const size_t sz)
  513. {
  514.   // Align sz up to the nearest multiple of ALIGNMENT.
  515.   // This is much faster than using multiplication
  516.   // and division.
  517.   return (sz + ALIGNMENT_MASK) & ~ALIGNMENT_MASK;
  518. }
  519.  
  520.  
  521. void hoardHeap::setIndex (int i) 
  522. {
  523.   _index = i; 
  524. }
  525.  
  526.  
  527. int hoardHeap::getIndex (void)
  528. {
  529.   return _index;
  530. }
  531.  
  532.  
  533.  
  534.  
  535. void hoardHeap::recycle (superblock * sb)
  536. {
  537.   assert (sb != NULL);
  538.   assert (sb->getOwner() == this);
  539.   assert (sb->getNumBlocks() > 1);
  540.   assert (sb->getNext() == NULL);
  541.   assert (sb->getPrev() == NULL);
  542.   assert (hoardHeap::numBlocks(sb->getBlockSizeClass()) > 1);
  543.  
  544. #ifndef CRYSTAL_HOARD
  545.   sb->insertBefore (_reusableSuperblocks);
  546.   _reusableSuperblocks = sb;
  547.   ++_reusableSuperblocksCount;
  548. #else
  549.   int sbClass = sb->getSuperblockClass();
  550.   assert (sbClass < SUPERBLOCK_CLASSES);
  551.   sb->insertBefore( _reusableSuperblocks[sbClass] );
  552.   _reusableSuperblocks[sbClass] = sb;
  553.   ++_reusableSuperblocksCount[sbClass];
  554. #endif
  555.   // printf ("count: %d => %d\n", getIndex(), _reusableSuperblocksCount);
  556. }
  557.  
  558.  
  559. superblock * hoardHeap::reuse (int sizeclass)
  560. {
  561.   // Make sure that we aren't using a sizeclass
  562.   // that is too big for a 'normal' superblock.
  563.   if (hoardHeap::numBlocks(sizeclass) <= 1) {
  564.     return NULL;
  565.   }
  566.  
  567. #ifndef CRYSTAL_HOARD
  568.   if (_reusableSuperblocks == NULL) {
  569.     return NULL;
  570.   }
  571.  
  572.   // Pop off a superblock from the reusable-superblock list.
  573.   assert (_reusableSuperblocksCount > 0);
  574.   superblock * sb = _reusableSuperblocks;
  575.   _reusableSuperblocks = sb->getNext();
  576.   sb->remove();
  577.   assert (sb->getNumBlocks() > 1);
  578.   --_reusableSuperblocksCount;
  579. #else
  580.   int sbClass = superblockClass(sizeclass);
  581.   assert ( sbClass < SUPERBLOCK_CLASSES );
  582.  
  583.   // Check for reusable superblocks of this size class
  584.   if (_reusableSuperblocks[sbClass] == NULL) {
  585.     return NULL;
  586.   }
  587.  
  588.   // Pop off a superblock from the reusable-superblock list.
  589.   assert (_reusableSuperblocksCount[sbClass] > 0);
  590.   superblock * sb = _reusableSuperblocks[sbClass];
  591.   _reusableSuperblocks[sbClass] = sb->getNext();
  592.   sb->remove();
  593.   assert (sb->getNumBlocks() > 1);
  594.   --_reusableSuperblocksCount[sbClass];
  595. #endif  // CRYSTAL_HOARD
  596.  
  597.   // Reformat the superblock if necessary.
  598.   if (sb->getBlockSizeClass() != sizeclass) {
  599.     decStats (sb->getBlockSizeClass(),
  600.           sb->getNumBlocks() - sb->getNumAvailable(),
  601.           sb->getNumBlocks());
  602.     
  603.     sb = new ((char *) sb) superblock (numBlocks(sizeclass), sizeclass, this);
  604.  
  605.     incStats (sizeclass,
  606.           sb->getNumBlocks() - sb->getNumAvailable(),
  607.           sb->getNumBlocks());
  608.   }
  609.  
  610.   assert (sb->getOwner() == this);
  611.   assert (sb->getBlockSizeClass() == sizeclass);
  612.   return sb;
  613. }
  614.  
  615. #endif // _HEAP_H_
  616.